package cn.shop.front.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.shop.front.entity.payModule.FkNotifyReq;
import cn.shop.front.entity.payModule.NotifyReq;
import cn.shop.front.entity.req.FundDetailQueryReq;
import cn.shop.front.entity.req.ScanTransactionBatchReq;
import cn.shop.front.entity.req.TransactionBatchReq;
import cn.shop.front.service.*;
import cn.shop.front.util.CurrentUserUtil;
import cn.shop.transcation.TransactionRecord.entity.RechargeInfoReq;
import cn.shop.transcation.TransactionRecord.entity.ScanTransactionRecord;
import cn.shop.transcation.TransactionRecord.entity.TransactionRecord;
import cn.shop.transcation.backPaymentChannelModule.entity.BackPaymentChannel;
import cn.shop.transcation.detail.entity.TransactionRecordQueryReq;
import cn.shop.transcation.frontUserModule.FrontUser;
import cn.shop.transcation.order.entity.Order;
import cn.shop.transcation.promotionsModule.Promotions;
import cn.shop.utils.ApiCode;
import cn.shop.utils.ApiResult;
import cn.shop.utils.Putif;
import cn.shop.utils.constant.PromotionsConstant;
import cn.shop.utils.exception.ServiceException;
import cn.shop.validation.Pc;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 交易接口
 *
 * @author jzw
 * @since 2021-12-13 10:49:40
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/api/v1/transactionRecord")
public class TransactionRecordController {

	/**
	 * 服务对象
	 */
	@Resource
	private TransactionRecordService transactionRecordService;
	@Resource
	private BackPaymentChannelService channelService;
	@Resource
	private FrontUserService frontUserService;
	@Resource
	private NotifyService notifyService;
	@Resource
	private PromotionsService promotionsService;
	@Resource
	private AppTransactionService appTransactionService;

	/**
	 * app购买商品
	 *
	 * @param transactionRecord 实体对象
	 * @return 新增结果
	 * @author jzw
	 * @since 2021-12-13 10:49:40
	 */
	@SaCheckLogin
	@PostMapping("insert")
	public ApiResult<Map<String, Object>> insert(@Validated @RequestBody TransactionRecord transactionRecord) throws InterruptedException {
		long userId = CurrentUserUtil.getUserId();
		checkIsCertification(userId);
		boolean success = appTransactionService.createRecord(userId, transactionRecord);
		if (success) {
			transactionRecordService.receive(transactionRecord.getProductId());
		}
		return ApiResult.result(success);
	}

	/**
	 * 购买商品
	 *
	 * @param transactionRecord 实体对象
	 * @return 新增结果
	 * @author jzw
	 * @since 2021-12-13 10:49:40
	 */
	@SaCheckLogin
	@PostMapping("/pc/insert")
	public ApiResult<Map<String, Object>> insert(@Validated @RequestBody TransactionRecord transactionRecord, HttpServletRequest request) throws InterruptedException {
		long userId = CurrentUserUtil.getUserId();
		checkIsCertification(userId);
		boolean success = transactionRecordService.createRecord(userId, transactionRecord, request);
		if (success) {
			transactionRecordService.receive(transactionRecord.getProductId());
		}
		return ApiResult.result(success);
	}

	/**
	 * 余额批量购买
	 * @param record
	 * @param request
	 * @return
	 * @throws InterruptedException
	 */
	@SaCheckLogin
	@PostMapping("/batch/insert")
	public ApiResult<Map<String, Object>> insertBatch(@Validated @RequestBody TransactionBatchReq record, HttpServletRequest request) throws InterruptedException {
		long userId = CurrentUserUtil.getUserId();
		checkIsCertification(userId);
		List<Order> updates = transactionRecordService.createRecord(userId, record, request);
		for (Order update : updates) {
			transactionRecordService.receive(update.getId());
		}
		if (updates.size() < record.getProductIds().size()) {
			return new ApiResult<>(ApiCode.SUCCESS_SEND_FAIL, "交易成功，但是部分商品已下架或被其他人购买", null);
		} else {
			return ApiResult.success("交易成功");
		}
	}

	/**
	 * 购买商品
	 *
	 * @param transactionRecord 实体对象
	 * @return 新增结果
	 * @author lyh
	 * @since 2022-05-11
	 */
	@SaCheckLogin
	@PostMapping("/buy")
	public ApiResult<Object> buy(@Validated @RequestBody ScanTransactionRecord transactionRecord, HttpServletRequest request) throws InterruptedException {
		long userId = CurrentUserUtil.getUserId();
		checkIsCertification(userId);
		return ApiResult.success(transactionRecordService.createRecord(userId, transactionRecord, request));
	}

	/**
	 * 扫码批量购买
	 * @param record
	 * @param request
	 * @return
	 * @throws InterruptedException
	 */
	@SaCheckLogin
	@PostMapping("/batch/buy")
	public ApiResult<Object> buyBatch(@Validated @RequestBody ScanTransactionBatchReq record, HttpServletRequest request) throws InterruptedException {
		long userId = CurrentUserUtil.getUserId();
		checkIsCertification(userId);
		return ApiResult.success(transactionRecordService.createRecord(userId, record, request));
	}

	/**
	 * 获取活动信息
	 *
	 * @return 返回结果
	 */
	//@SaCheckLogin
	@GetMapping("/prize")
	public ApiResult<Map<String, Object>> prizePool() {
		Promotions promotions = promotionsService.getOne(Wrappers.<Promotions>lambdaQuery()
				.eq(Promotions::getKey, PromotionsConstant.PRIZE_POOL));
		if (promotions == null) {
			return ApiResult.success();
		}
		return ApiResult.success(Putif.start()
						.anyway("prize", promotions.getPrizePool())
						.anyway("enable", promotions.getEnable())
						.anyway("content", promotions.getContent())
				.get());
	}

	/**
	 * 获取支付通道
	 *
	 * @return 返回结果
	 */
	@SaCheckLogin
	@GetMapping("/channel")
	public ApiResult<List<Map<String, Object>>> channelList() {
		List<BackPaymentChannel> channels = channelService.lambdaQuery()
				.eq(BackPaymentChannel::getDefaultChannel, true)
				.eq(BackPaymentChannel::getChannel, 0)
				.list();
		return ApiResult.success(channels.stream()
				.map(c -> Putif.start()
						.anyway("id", c.getId())
						.anyway("name", c.getName())
						.anyway("type", c.getType())
						.anyway("rate", c.getRate())
						.get())
				.collect(Collectors.toList()));
	}

	/**
	 * 充值
	 *
	 * @param rechargeInfoReq 实体对象
	 * @return 新增结果
	 * @author jzw
	 * @since 2021-12-13 10:49:40
	 */
	@SaCheckLogin
	@PostMapping("recharge")
	public ApiResult<Object> recharge(@Validated(Pc.class) @RequestBody RechargeInfoReq rechargeInfoReq, HttpServletRequest request) {
		long userId = CurrentUserUtil.getUserId();
		//checkIsCertification(userId);
		FrontUser user = frontUserService.getById(userId);
		if (user == null || StrUtil.isBlank(user.getIdentityCard()) || StrUtil.isBlank(user.getName())) {
			BigDecimal amount = new BigDecimal(rechargeInfoReq.getAmount());
			if (NumberUtil.isGreater(amount, BigDecimal.valueOf(2000))) {
				throw new ServiceException("请先进行实名认证", ApiCode.NOT_REAL_NAME);
			}
			BigDecimal sum = transactionRecordService.todayRecord(userId);
			if (NumberUtil.isGreater(sum, BigDecimal.valueOf(5000))) {
				throw new ServiceException("请先进行实名认证", ApiCode.NOT_REAL_NAME);
			}
		}
		return ApiResult.success(transactionRecordService.recharge(rechargeInfoReq, request));
	}

	/**
	 * 校验是否充值成功
	 *
	 * @param id 主键
	 * @return 单条数据
	 */
	@GetMapping("checkRecharge/{id}")
	public ApiResult<Map<String, Object>> checkRecharge(@PathVariable Serializable id) {
		return ApiResult.result(transactionRecordService.checkRecharge(id));
	}

	/**
	 * fk支付回调接口
	 *
	 * @param payCallback
	 * @return
	 */
	@PostMapping("/{alias}/fknotify")
	public String fkNotify(@RequestBody FkNotifyReq payCallback, @PathVariable String alias) {
		String notify = notifyService.fkNotify(payCallback, alias);
		log.info("fk充值回调:{}, 处理结果: {}", payCallback, notify);
		return notify;
	}

	/**
	 * fk购买回调接口
	 *
	 * @param payCallback
	 * @return
	 */
	@PostMapping("/{alias}/{channelId}/fkordernotify")
	public String fkOrderNotify(@PathVariable long channelId, @RequestBody FkNotifyReq payCallback, @PathVariable String alias) {
		System.err.println(payCallback);
		String notify = notifyService.fkOrderNotify(payCallback, channelId, alias);
		System.err.println(notify);
		log.info("fk购买回调:{}, 处理结果: {}", payCallback, notify);
		return notify;
	}

	@PostMapping("/{alias}/{channelId}/fkordernotify/batch")
	public String fkOrderNotifyBatch(@PathVariable long channelId, @RequestBody FkNotifyReq payCallback, @PathVariable String alias) {
		System.err.println(payCallback);
		String notify = notifyService.fkOrderNotifyBatch(payCallback, channelId, alias);
		System.err.println(notify);
		log.info("fk批量购买回调:{}, 处理结果: {}", payCallback, notify);
		return notify;
	}


	/**
	 * dy支付回调接口
	 *
	 * @param payCallback
	 * @return
	 */
	@PostMapping("/{alias}/notify")
	public String notify(NotifyReq payCallback, @PathVariable String alias) {
		System.err.println(payCallback);
		String notify = notifyService.notify(payCallback, alias);
		System.err.println(notify);
		return notify;
	}

	/**
	 * 购买回调接口
	 *
	 * @param payCallback
	 * @return
	 */
	@PostMapping("/{alias}/{channelId}/ordernotify")
	public String orderNotify(@PathVariable long channelId, NotifyReq payCallback, @PathVariable String alias) {
		System.err.println(payCallback);
		String notify = notifyService.orderNotify(payCallback, channelId, alias);
		System.err.println(notify);
		return notify;
	}

	@PostMapping("/{alias}/{channelId}/ordernotify/batch")
	public String orderNotifyBatch(@PathVariable long channelId, NotifyReq payCallback, @PathVariable String alias) {
		System.err.println(payCallback);
		String notify = notifyService.orderNotifyBatch(payCallback, channelId, alias);
		System.err.println(notify);
		return notify;
	}


	/**
	 * 查询交易记录
	 *
	 * @param req 查询条件
	 * @return 返回结果
	 */
	@SaCheckLogin
	@GetMapping("/list")
	public ApiResult<Map<String, Object>> list(FundDetailQueryReq req) {
		TransactionRecordQueryReq r = new TransactionRecordQueryReq();
		/*r.setCurrent(req.getCurrent());
		r.setSize(req.getSize());*/
		// 固定30条
		r.setCurrent(1);
		r.setSize(30);
		if (req.getBeginTime() != null) {
			r.setBeginTime(LocalDateTime.of(req.getBeginTime(), LocalTime.now()));
		}
		if (req.getEndTime() != null) {
			r.setEndTime(LocalDateTime.of(req.getEndTime(), LocalTime.now()));
		}
		r.setType(req.getType());
		Map<String, Object> data = transactionRecordService.recordList(CurrentUserUtil.getUserId(), r);
		return ApiResult.success(data);
	}

	/**
	 * 查询交易记录(APP)
	 *
	 * @param req 查询条件
	 * @return 返回结果
	 */
	@SaCheckLogin
	@GetMapping("/itemlist")
	public ApiResult<Map<String, Object>> itemList(FundDetailQueryReq req) {
		TransactionRecordQueryReq r = new TransactionRecordQueryReq();
		r.setCurrent(req.getCurrent());
		r.setSize(req.getSize());
		r.setType(req.getType());
		r.setOrderId(req.getOrderId());
		if (req.getBeginTime() != null) {
			r.setBeginTime(LocalDateTime.of(req.getBeginTime(), LocalTime.now()));
		}
		if (req.getEndTime() != null) {
			r.setEndTime(LocalDateTime.of(req.getEndTime(), LocalTime.now()));
		}
		Map<String, Object> data = transactionRecordService.recordList1(CurrentUserUtil.getUserId(), r);
		return ApiResult.success(data);
	}

	/**
	 * 查询账单记录(APP)
	 *
	 * @param req 查询条件
	 * @return 返回结果
	 */
	@SaCheckLogin
	@GetMapping("/billlist")
	public ApiResult<Map<String, Object>> billList(FundDetailQueryReq req) {
		TransactionRecordQueryReq r = new TransactionRecordQueryReq();
		r.setCurrent(req.getCurrent());
		r.setSize(req.getSize());
		r.setType(req.getType());
		if (req.getBeginTime() != null) {
			r.setBeginTime(LocalDateTime.of(req.getBeginTime(), LocalTime.now()));
		}
		if (req.getEndTime() != null) {
			r.setEndTime(LocalDateTime.of(req.getEndTime(), LocalTime.now()));
		}
		Map<String, Object> data = transactionRecordService.recordList2(CurrentUserUtil.getUserId(), r);
		return ApiResult.success(data);
	}

	private void checkIsCertification(long userId) {
		FrontUser user = frontUserService.getById(userId);
		if (user == null || StrUtil.isBlank(user.getIdentityCard()) || StrUtil.isBlank(user.getName())) {
			throw new ServiceException("请先进行实名认证");
		}
		if (StrUtil.isBlank(user.getPhone())) {
			throw new ServiceException("请完善手机号");
		}
	}
}

